#include "../common/dispatcher.hpp"
#include "../client/rpc_client.hpp"
#include "rpc_router.hpp"
#include "rpc_registry.hpp"
// #include "rpc_topic.hpp"

namespace myrpc 
{
    namespace server 
    {
        // 业务：对服务提供者和发现者的数据管理
        // 注册中心服务端：只需要针对服务注册与发现请求进行处理即可
        class RegistryServer 
        {
        public:
            using ptr = std::shared_ptr<RegistryServer>;
            RegistryServer(int port)
                : _pd_manager(std::make_shared<PDManager>())
                , _dispatcher(std::make_shared<myrpc::Dispatcher>())
            {
                auto service_cb = std::bind(&PDManager::onServiceRequest, _pd_manager.get(),
                                                            std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<ServiceRequest>(MType::REQ_SERVICE, service_cb);
                
                _server = myrpc::ServerFactory::create(port);
                auto message_cb = std::bind(&myrpc::Dispatcher::onMessage, _dispatcher.get(), 
                                                            std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);
                // 7、这个地方其实就是进行了回调函数的注册，
                // setCloseCallback这个接口注册的是，当关闭连接的时候，会调用的函数
                auto close_cb = std::bind(&RegistryServer::onConnShutdown, this, std::placeholders::_1);
                _server->setCloseCallback(close_cb);
            }
            void start() 
            {
                _server->start();
            }
        private:
            void onConnShutdown(const BaseConnection::ptr &conn) 
            {
                // 8、就是会执行这里的逻辑
                _pd_manager->onConnShutdown(conn);
            }
        private:
            PDManager::ptr _pd_manager;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };

        class RpcServer 
        {
        public:
            using ptr = std::shared_ptr<RpcServer>;
            // rpc_server端有两套地址信息：
            //  1. rpc服务提供端地址信息--必须是rpc服务器对外访问地址（云服务器---监听地址和访问地址不同）
            //  2. 注册中心服务端地址信息 -- 启用服务注册后，连接注册中心进行服务注册用的
            RpcServer(const Address &access_addr, 
                bool enableRegistry = false, 
                const Address &registry_server_addr = Address())
                : _enableRegistry(enableRegistry)
                , _access_addr(access_addr)
                , _router(std::make_shared<myrpc::server::RpcRouter>())
                , _dispatcher(std::make_shared<myrpc::Dispatcher>()) 
            {
                
                if (enableRegistry) 
                {
                    _reg_client = std::make_shared<client::RegistryClient>(
                                                    registry_server_addr.first, registry_server_addr.second);
                }
                //当前成员server是一个rpcserver，用于提供rpc服务的
                auto rpc_cb = std::bind(&RpcRouter::onRpcRequest, _router.get(), 
                                                    std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<myrpc::RpcRequest>(myrpc::MType::REQ_RPC, rpc_cb);

                _server = myrpc::ServerFactory::create(access_addr.second);
                auto message_cb = std::bind(&myrpc::Dispatcher::onMessage, _dispatcher.get(), 
                                                    std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);
            }

            void registerMethod(const ServiceDescribe::ptr &service) 
            {
                if (_enableRegistry) 
                {
                    _reg_client->registryMethod(service->method(), _access_addr);
                }
                _router->registerMethod(service);
            }
            void start() 
            {
                _server->start();
            }
        private:
            bool _enableRegistry;
            Address _access_addr;
            client::RegistryClient::ptr _reg_client;
            RpcRouter::ptr _router;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };
    }
}